简介
之前一直使用httpclient进行爬虫的接口,但是一直对实现的底层原理不是很理解。尤其是httpclient这个对象十分庞大。
对这个类的详细的理解是出于对http底层的原理有了一定的理解之后,想着java这边对httpclient的封装又是如何支持http协议的,出于这个好奇心,就花了一天的时间去研究,总算有所收获。
如何构建一个可做请求的Httpclient
这节的内容主要参考了webmagic的源码里面的构造,主要涉及到三个主要对象的构建,HttpClient,HttpUriRequest,HttpClientContext。
HttpClient对象
|
|
解析: 上述代码主要是设置了UserAgent,Socket的一些基本配置,DefaultHttpRequestRetryHandler,HttpRequestInterceptor,ConnectionManager。
其中对于ConnectionManager的设置,我这边进行了深入的研究。
ConnectionManager
|
|
DefaultMaxPerRoute代表一个TCP连接最大可以连接的不同远程主机(ip+端口)最大数量为100
MaxTotal代表主机最大的连接数相当于最大可以开200个端口进行tcp连接。
PoolingHttpClientConnectionManager与BasicHttpClientConnectionManager的区别:
前者代表多线程,后者代表单线程。
HttpUriRequest
|
|
主要是设置这次请求的Proxy和Header。
HttpClientContext
主要用于设置这次请求需要的cookie。
如果需要使用HttpClient池,并且想要做到一次登录的会话供多个HttpClient连接使用,就需要自己保存会话信息。因为客户端的会话信息是保存在cookie中的(JSESSIONID),所以只需要将登录成功返回的cookie复制到各个HttpClient使用即可。
使用Cookie的方法有两种,可以自己使用CookieStore来保存(见TestCookieStore()方法),也可以通过HttpClientContext上下文来维持(见TestContext()方法)。
使用CookieStore:
|
|
使用context方式
|
|
TCP连接
端对端的连接,端口到端口的连接。
用wireshark抓包发现,每一个http请求都是先发起一个tcp的连接,每个tcp都带有一个端口。
端口的复用
[Full request URI: http://www.cnblogs.com/cate/java/] :Source Port: 55212 Destination Port: 80
[Full request URI: http://www.cnblogs.com/bundles/aggsite.css?v=IhfFDNk6saBQuSizNqMno4eFb5L3OoXlsUCqkaSgNvA1] :Source Port: 55212 Destination Port: 80
[Full request URI: http://www.cnblogs.com/bundles/aggsite.js?v=vWqa5z-vvnUBiauXGl6S0-ZbtOAq_fbE-A1hKZngtlw1] Source Port: 55213 Destination Port: 80
当用chrome访问一个链接http://www.cnblogs.com/cate/java/时,其中一个端口55212分别进行了两次http的获取,一次是html,一次是css。